home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / wrlib / xutil.c < prev   
Encoding:
C/C++ Source or Header  |  1999-04-20  |  6.8 KB  |  285 lines

  1. /* xutil.c - utility functions for X
  2.  * 
  3.  *  Raster graphics library
  4.  *
  5.  *  Copyright (c) 1997 Alfredo K. Kojima 
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Library General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *  
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Library General Public License for more details.
  16.  *  
  17.  *  You should have received a copy of the GNU Library General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #include <config.h>
  23.  
  24.  
  25. #include <X11/Xlib.h>
  26. #include <X11/Xutil.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30.  
  31. #include <assert.h>
  32.  
  33. #ifdef XSHM
  34. #include <sys/ipc.h>
  35. #include <sys/shm.h>
  36. #endif /* XSHM */
  37.  
  38. #include "wraster.h"
  39.  
  40.  
  41. #ifdef XSHM
  42.  
  43. static int shmError;
  44.  
  45. static int (*oldErrorHandler)();
  46.  
  47. static int
  48. errorHandler(Display *dpy, XErrorEvent *err)
  49. {
  50.     shmError=1;
  51.     if(err->error_code!=BadAccess)
  52.     (*oldErrorHandler)(dpy, err);
  53.  
  54.     return 0;
  55. }
  56.  
  57.  
  58. #endif
  59.  
  60.  
  61. RXImage*
  62. RCreateXImage(RContext *context, int depth, unsigned width, unsigned height)
  63. {
  64.     RXImage *rximg;
  65.     Visual *visual = context->visual;
  66.     
  67.     rximg = malloc(sizeof(RXImage));
  68.     if (!rximg) {
  69.     RErrorCode = RERR_NOMEMORY;
  70.     return NULL;
  71.     }
  72.     
  73. #ifndef XSHM
  74.     rximg->image = XCreateImage(context->dpy, visual, depth,
  75.                 ZPixmap, 0, NULL, width, height, 8, 0);
  76.     if (!rximg->image) {
  77.     free(rximg);
  78.     RErrorCode = RERR_XERROR;
  79.     return NULL;
  80.     }
  81.     rximg->image->data = malloc(rximg->image->bytes_per_line*height);
  82.     if (!rximg->image->data) {
  83.     XDestroyImage(rximg->image);
  84.     free(rximg);
  85.     RErrorCode = RERR_NOMEMORY;
  86.     return NULL;
  87.     }
  88.     
  89. #else /* XSHM */    
  90.     if (!context->attribs->use_shared_memory) {
  91.     retry_without_shm:
  92.  
  93.     context->attribs->use_shared_memory = 0;
  94.     rximg->is_shared = 0;
  95.     rximg->image = XCreateImage(context->dpy, visual, depth,
  96.                     ZPixmap, 0, NULL, width, height, 8, 0);
  97.     if (!rximg->image) {
  98.         free(rximg);
  99.         RErrorCode = RERR_XERROR;
  100.         return NULL;
  101.     }
  102.     rximg->image->data = malloc(rximg->image->bytes_per_line*height);
  103.     if (!rximg->image->data) {
  104.         XDestroyImage(rximg->image);
  105.         free(rximg);
  106.         RErrorCode = RERR_NOMEMORY;
  107.         return NULL;
  108.     }
  109.     } else {
  110.     rximg->is_shared = 1;
  111.  
  112.     rximg->info.readOnly = False;
  113.  
  114.     rximg->image = XShmCreateImage(context->dpy, visual, depth,
  115.                        ZPixmap, NULL, &rximg->info, width, 
  116.                        height);    
  117.  
  118.     rximg->info.shmid = shmget(IPC_PRIVATE, 
  119.                    rximg->image->bytes_per_line*height,
  120.                    IPC_CREAT|0777);
  121.     if (rximg->info.shmid < 0) {
  122.         context->attribs->use_shared_memory = 0;
  123.         perror("wrlib:could not allocate shared memory segment");
  124.         XDestroyImage(rximg->image);
  125.         goto retry_without_shm;
  126.     }
  127.     
  128.     rximg->info.shmaddr = shmat(rximg->info.shmid, 0, 0);
  129.     if (rximg->info.shmaddr == (void*)-1) {
  130.         context->attribs->use_shared_memory = 0;
  131.         if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
  132.         perror("wrlib:shmctl");
  133.         perror("wrlib:could not allocate shared memory");
  134.         XDestroyImage(rximg->image);
  135.         goto retry_without_shm;
  136.     }
  137.     
  138.     shmError = 0;
  139.     XSync(context->dpy, False);
  140.     oldErrorHandler = XSetErrorHandler(errorHandler);
  141.     XShmAttach(context->dpy, &rximg->info);    
  142.     XSync(context->dpy, False);
  143.     XSetErrorHandler(oldErrorHandler);
  144.  
  145.     rximg->image->data = rximg->info.shmaddr;
  146. /*    rximg->image->obdata = &(rximg->info);*/
  147.  
  148.     if (shmError) {
  149.         context->attribs->use_shared_memory = 0;
  150.         XDestroyImage(rximg->image);
  151.         if (shmdt(rximg->info.shmaddr) < 0)
  152.         perror("wrlib:shmdt");
  153.         if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
  154.         perror("wrlib:shmctl");
  155. /*        printf("wrlib:error attaching shared memory segment to XImage\n");
  156.  */
  157.         goto retry_without_shm;
  158.     }
  159.     }
  160. #endif /* XSHM */
  161.     
  162.     return rximg;
  163. }
  164.  
  165.  
  166. void
  167. RDestroyXImage(RContext *context, RXImage *rximage)
  168. {
  169. #ifndef XSHM
  170.     XDestroyImage(rximage->image);
  171. #else /* XSHM */
  172.     if (rximage->is_shared) {
  173.     XSync(context->dpy, False);
  174.     XShmDetach(context->dpy, &rximage->info);
  175.     XDestroyImage(rximage->image);
  176.     if (shmdt(rximage->info.shmaddr) < 0)
  177.         perror("wrlib:shmdt");
  178.     if (shmctl(rximage->info.shmid, IPC_RMID, 0) < 0)
  179.         perror("wrlib:shmctl");
  180.     } else {
  181.     XDestroyImage(rximage->image);
  182.     }
  183. #endif
  184.     free(rximage);
  185. }
  186.  
  187.  
  188. static unsigned
  189. getDepth(Display *dpy, Drawable d)
  190. {
  191.     Window w;
  192.     int foo;
  193.     unsigned bar;
  194.     unsigned depth;
  195.     
  196.     XGetGeometry(dpy, d, &w, &foo, &foo, &bar, &bar, &bar, &depth);
  197.     
  198.     return depth;
  199. }
  200.  
  201.  
  202.  
  203. RXImage*
  204. RGetXImage(RContext *context, Drawable d, int x, int y,
  205.        unsigned width, unsigned height)
  206. {
  207.     RXImage *ximg = NULL;
  208.  
  209. #ifdef XSHM
  210.     if (context->attribs->use_shared_memory && 0) {
  211.     ximg = RCreateXImage(context, getDepth(context->dpy, d),
  212.                  width, height);
  213.  
  214.     if (ximg && !ximg->is_shared) {
  215.         RDestroyXImage(context, ximg);
  216.         ximg = NULL;
  217.     }
  218.     if (ximg) {
  219.         XShmGetImage(context->dpy, d, ximg->image, x, y, AllPlanes);
  220.     }
  221.     }
  222.     if (!ximg) {
  223.     ximg = malloc(sizeof(RXImage));
  224.     if (!ximg) {
  225.         RErrorCode = RERR_NOMEMORY;
  226.         return NULL;
  227.     }
  228.     ximg->is_shared = 0;
  229.     ximg->image = XGetImage(context->dpy, d, x, y, width, height,
  230.                 AllPlanes, ZPixmap);
  231.     }
  232.     return ximg;
  233. #else /* !XSHM */
  234.     ximg = malloc(sizeof(RXImage));
  235.     if (!ximg) {
  236.     RErrorCode = RERR_NOMEMORY;
  237.     return NULL;
  238.     }
  239.     
  240.     ximg->image = XGetImage(context->dpy, d, x, y, width, height,
  241.                 AllPlanes, ZPixmap);
  242.  
  243.     return ximg;
  244. #endif /* !XSHM */
  245. }
  246.  
  247.  
  248. void
  249. RPutXImage(RContext *context, Drawable d, GC gc, RXImage *ximage, int src_x,
  250.        int src_y, int dest_x, int dest_y, 
  251.        unsigned int width, unsigned int height)
  252. {
  253. #ifndef XSHM
  254.     XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x,
  255.           dest_y, width, height);
  256. #else
  257.     if (ximage->is_shared) {
  258.     XShmPutImage(context->dpy, d, gc, ximage->image, src_x, src_y,
  259.              dest_x, dest_y, width, height, False);
  260.     } else {
  261.     XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x,
  262.           dest_y, width, height);
  263.     }
  264.     XFlush(context->dpy);
  265. #endif /* XSHM */
  266. }
  267.  
  268.  
  269. #ifdef XSHM
  270. Pixmap
  271. R_CreateXImageMappedPixmap(RContext *context, RXImage *rximage)
  272. {
  273.     Pixmap pix;
  274.  
  275.     pix = XShmCreatePixmap(context->dpy, context->drawable, 
  276.                rximage->image->data, &rximage->info,
  277.                rximage->image->width, rximage->image->height,
  278.                rximage->image->depth);
  279.  
  280.     return pix;
  281. }
  282.  
  283. #endif /* XSHM */
  284.  
  285.